<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/blog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/blog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/blog/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">










<meta name="description" content="Java源码/设计模式/个人记录">
<meta property="og:type" content="website">
<meta property="og:title" content="arry&#39;s blog">
<meta property="og:url" content="https://arrycoder.gitee.io/page/3/index.html">
<meta property="og:site_name" content="arry&#39;s blog">
<meta property="og:description" content="Java源码/设计模式/个人记录">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="arry&#39;s blog">
<meta name="twitter:description" content="Java源码/设计模式/个人记录">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Muse',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://arrycoder.gitee.io/page/3/">





  <title>arry's blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?97f9adfda8d04eb91dd054a98264d191";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  
  
    
  

  <div class="container sidebar-position-left 
  page-home">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">arry's blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/blog/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/blog/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/git/merge/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/git/merge/" itemprop="url">merge</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-05-08T10:41:30+08:00">
                2020-05-08
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/git/" itemprop="url" rel="index">
                    <span itemprop="name">git</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p><strong><em>merge</em></strong>就是指定一个<strong>branch</strong>，从该<strong>branch</strong>与本地branch分叉的位置起所有的commit，合并到当前<strong>commit</strong>，并生成一个新的<strong>commit</strong>，git会为这个commit生成一些简单的提交信息，可以直接提交。</p>
<h2 id="冲突"><a href="#冲突" class="headerlink" title="冲突"></a>冲突</h2><p>在两个分支下，对不同对文件进行开发，或者相同文件，但是改的内容不同，git会自动将这些改动合并。但是如果两个分支修改了同一个部分的内容的时候，就无法自动完成，需要人工手动解决冲突之后，再进行提交。</p>
<p><img src="https://user-gold-cdn.xitu.io/2017/11/21/15fddc2a9d759d8e?imageslim" alt="img"></p>
<p><img src="/blog/git/merge/image-20200508110248978.png" alt="image-20200508110248978"></p>
<h2 id="放弃解决冲突"><a href="#放弃解决冲突" class="headerlink" title="放弃解决冲突"></a>放弃解决冲突</h2><p>git merge –abort</p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/git/概念解释/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/git/概念解释/" itemprop="url">git概念</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-05-08T10:03:51+08:00">
                2020-05-08
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/git/" itemprop="url" rel="index">
                    <span itemprop="name">git</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>commit: 每次的提交叫做一个commit</p>
<p>敲下git log的时候，会出现提交历史，而这些值都代表着什么意思呢？</p>
<p><img src="/blog/git/概念解释/image-20200508100604513.png" alt="image-20200508100604513"></p>
<h2 id="分开解析"><a href="#分开解析" class="headerlink" title="分开解析"></a>分开解析</h2><p><strong>commit</strong>后面跟着一串字符，这串字符相当于这个<strong>commit</strong>的身份证（SHA-1校验和），每个SHA-1值的重复概率非常低，因此可以用这个值来代表这个<strong>commit</strong>。通常也可以只使用这个值的前几位来代替，比如<strong>8898ee5</strong>甚至<strong>8898</strong></p>
<h3 id="HEAD"><a href="#HEAD" class="headerlink" title="HEAD"></a>HEAD</h3><p><strong>HEAD</strong>是指向当前工作目录下<strong>commit</strong>的引用，比如这个HEAD现在指向的是本地工作分支（feature/0424_yz）的最新一个<strong>commit</strong>（8898……），当你切换分支或者改变当前<strong>commit</strong>的时候，<strong>HEAD</strong>都会跟随过去，所以，你永远可以用HEAD操作当前<strong>commit</strong>。</p>
<h3 id="branch"><a href="#branch" class="headerlink" title="branch"></a>branch</h3><p>HEAD -&gt; feature/0424_yz, origin/feature/0424_yz 代表着当前工作目录的分支是feature/0424_yz。<strong>branch</strong>也是一种commit的引用，HEAD在指向branch的时候也是间接的指向了对应的commit。</p>
<p>在commit的时候，HEAD会拖着master往前进</p>
<p><img src="/blog/git/概念解释/15fd779f983c81e7.gif" alt="img"></p>
<p>当在本地clone远程仓库的时候，会把远程的<strong>master</strong> checkout 成为本地的默认分支。而在本地创建分支的时候，就会在原有的基础上出现分叉。</p>
<p><img src="/blog/git/概念解释/branch-2.gif" alt="img"></p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/设计模式/使用观察者模式优化代码/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/设计模式/使用观察者模式优化代码/" itemprop="url">使用观察者模式优化代码</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-04-10T10:23:53+08:00">
                2020-04-10
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>在我们的交易系统中，都是以订单为载体，通过客户和商家的操作来决定订单节点的流转，同时决定着下一步该做哪些操作，简单画个图来看一下。</p>
<p><img src="/blog/设计模式/使用观察者模式优化代码/%E8%AE%A2%E5%8D%95%E6%B5%81%E7%A8%8B.jpg" alt="订单流程图"></p>
<p>我们可以看到，在每一个动作之后都需要将订单同步到订单索引，同时，在特定节点的时候，还需要通知第三方平台做相应的操作。（这里只是个简单的流程图，实际的流程比这个要复杂很多）</p>
<p>在没使用到监听器模式之前，<em>代码是这样的</em></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">createOrder</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  check()</span><br><span class="line">  ···</span><br><span class="line">  ···创建订单流程</span><br><span class="line">  ···</span><br><span class="line">  <span class="comment">// 索引消息发送</span></span><br><span class="line">  indexProducer.send(order);</span><br><span class="line">  <span class="comment">// 通知销售有人下单</span></span><br><span class="line">  messageCenter.send(order);</span><br><span class="line">  <span class="comment">// 创建支付单</span></span><br><span class="line">  payTransactionProducer.send(tran);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  check()</span><br><span class="line">  ···</span><br><span class="line">  ···创建订单流程</span><br><span class="line">  ···</span><br><span class="line">  <span class="comment">// 索引消息发送</span></span><br><span class="line">  indexProducer.send(order);</span><br><span class="line">  <span class="comment">// 通知销售已支付，去发货</span></span><br><span class="line">  messageCenter.send(order);</span><br><span class="line">	<span class="comment">// 创建物流单</span></span><br><span class="line">  logisticsOrderProducer.send(logistic);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样的代码就会产生几个问题：</p>
<ol>
<li><p>代码冗余</p>
<p>这个不必说了，每次状态变更都需要调用相同的代码，不仅写起来不够优雅，当你发送消息的参数改动的时候，也需要一个一个地方去修正，很浪费时间。</p>
</li>
<li><p>不利于扩展</p>
<p>产品说：“为了打入商户内部，我们要接入商户现有ERP系统，现在给👴把订单同步过去”。好了，这下，你又需要在每一个节点中加同步的方法，不仅麻烦，还容易出错。</p>
</li>
</ol>
<h2 id="观察者模式"><a href="#观察者模式" class="headerlink" title="观察者模式"></a>观察者模式</h2><p>本篇的重点不在于观察者模式，而在于优化代码。所以关于观察者模式就不介绍了。这里仅放个定义</p>
<blockquote>
<p>观察者模式(Observer Pattern)：定义对象之间的一种一对多依赖关系，使得每当一个对象状态发生改变时，其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅（Publish/Subscribe）模式、模型-视图（Model/View）模式、源-监听器（Source/Listener）模式或从属者（Dependents）模式。观察者模式是一种对象行为型模式。</p>
</blockquote>
<p>参考资料-&gt; <a href="https://blog.csdn.net/lovelion/article/details/17517213" title="设计模式" target="_blank" rel="noopener">设计模式</a></p>
<h2 id="Spring-EventListener"><a href="#Spring-EventListener" class="headerlink" title="Spring EventListener"></a>Spring EventListener</h2><p>Spring在4.2之后提供了基于注解的事件监听器，我们可以在任意被管理的bean下，使用 <strong>@EventListener</strong>注册监听器，使用ApplicationContext来发布事件。下面看下改造流程。</p>
<ol>
<li>定义一个订单事件,orderCode代表订单号，eventType代表事件类型。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="meta">@Setter</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OrderEvent</span> <span class="keyword">extends</span> <span class="title">ApplicationEvent</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Order order;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">private</span> EventType eventType;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">enum</span> EventType &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 创建</span></span><br><span class="line">        CREATE,</span><br><span class="line">        <span class="comment">// 支付</span></span><br><span class="line">        PAY,</span><br><span class="line">				<span class="comment">// 确认收货</span></span><br><span class="line">        CONFIRM</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ol start="2">
<li><p>创建事件监听器</p>
<p>通用的监听器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OrderIndexListener</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> IndexProducer indexProducer;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//这个注解支持监听器异步执行，可根据需要选择</span></span><br><span class="line">    <span class="meta">@Async</span></span><br><span class="line">    <span class="meta">@EventListener</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handlerOrderEvent</span><span class="params">(OrderEvent orderEvent)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 索引消息发送</span></span><br><span class="line">  			indexProducer.send(orderEvent.getOrder());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>收银台监听器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OrderIndexListener</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> PaymentOrderProducer paymentOrderProducer;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Async</span></span><br><span class="line">    <span class="meta">@EventListener</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handlerPay</span><span class="params">(OrderEvent orderEvent)</span> </span>&#123;</span><br><span class="line">      <span class="comment">// 特殊节点发送</span></span><br><span class="line">      <span class="keyword">if</span>(OrderEvent.EventType.CREATE.equals(orderEvent.getEventType())) &#123;</span><br><span class="line">        paymentOrderProducer.send(orderEvent.getOrder());</span><br><span class="line">      &#125;	</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>改造原来的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> ApplicationContext applicationContext;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">createOrder</span><span class="params">(Order order)</span> </span>&#123;</span><br><span class="line">  check()</span><br><span class="line">  ···</span><br><span class="line">  ···创建订单流程</span><br><span class="line">  ···</span><br><span class="line">  applicationContext.publish(<span class="keyword">new</span> OrderEvent(CREATE, order));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pay</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  check()</span><br><span class="line">  ···</span><br><span class="line">  ···创建订单流程</span><br><span class="line">  ···</span><br><span class="line">  applicationContext.publish(<span class="keyword">new</span> OrderEvent(CREATE, order));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ol>
<p>至此，改造已经完成。我们已经解决了之前那种写法里存在的问题，解藕了消息通知等工作，使得业务流程更加清晰，也更容易维护。</p>
<h2 id="需要避过的坑"><a href="#需要避过的坑" class="headerlink" title="需要避过的坑"></a>需要避过的坑</h2><ol>
<li><p>避免循环依赖</p>
<p>监听器和被观察者如果互相依赖，有可能会导致循环调用。最后导致系统崩溃</p>
</li>
<li><p>异步导致的调用乱序</p>
<p>如果使用了异步监听器，要注意给不同监听器加上@Order注解来保证调用不会乱序而影响订单流程。</p>
<p>如果有一些操作，比如设置了0元订单无需支付，直接从 “下单-&gt;待发货”，那么监听器会在很短时间内发送两条同步订单索引的消息，有可能会导致消费者收到消息的顺序是乱的，需要我们做额外的保证，例如延时发送，抛弃旧消息等等。</p>
</li>
<li><p>待扩展…</p>
</li>
</ol>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/Spring/SpringBoot-2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/Spring/SpringBoot-2/" itemprop="url">SpringBoot自动注册</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-01-07T15:34:16+08:00">
                2020-01-07
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/脑图/网络协议/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/脑图/网络协议/" itemprop="url">网络协议</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-01-06T10:03:10+08:00">
                2020-01-06
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p><img src="/blog/脑图/网络协议/%E7%BD%91%E7%BB%9C.png" alt="网络"></p>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/Spring/SpringBoot-1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/Spring/SpringBoot-1/" itemprop="url">SpringBoot启动原理</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-12-25T11:02:43+08:00">
                2019-12-25
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="SpringBoot-Jar包启动原理"><a href="#SpringBoot-Jar包启动原理" class="headerlink" title="SpringBoot Jar包启动原理"></a>SpringBoot Jar包启动原理</h2><h3 id="JAR的概念"><a href="#JAR的概念" class="headerlink" title="JAR的概念"></a>JAR的概念</h3><blockquote>
<p>在软件领域，JAR文件（Java归档，英语：Java Archive）是一种软件包文件格式，通常用于聚合大量的Java类文件、相关的元数据和资源（文本、图片等）文件到一个文件，以便开发Java平台应用软件或库。</p>
</blockquote>
<h3 id="可执行JAR包"><a href="#可执行JAR包" class="headerlink" title="可执行JAR包"></a>可执行JAR包</h3><p>一个JAR包能否执行就是看能否通过java -jar命令来直接运行程序。在平常的编码过程中，我们会大量的用到第三方的JAR包，比如FastJSON，Spring等等，这种包通常大部分无法直接运行。还有一种JAR包，可以直接通过上面的命令直接运行起来，这种我们称为<strong>可执行jar包</strong>。那虚拟机如何知道一个JAR包是否是可运行的，答案都在MANIFEST.MF文件里。</p>
<p>当我们打完jar包之后，会在根目录下创建一个META-INF目录，里面包含着一个MANIFEST.MF文件。MANIFEST文件里包含了这个jar包的元信息，也因为这个文件，JAR包就可以实现普通ZIP包所不能实现的很多功能，包括电子签名，版本控制，包装密封，安全性等。以下是官网对该文件的<a href="https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html" target="_blank" rel="noopener">简介</a>。</p>
<blockquote>
<p>JAR files support a wide range of functionality, including electronic signing, version control, package sealing, and others. What gives a JAR file this versatility? The answer is the JAR file’s <em>manifest</em>.</p>
<p>The manifest is a special file that can contain information about the files packaged in a JAR file. By tailoring this “meta” information that the manifest contains, you enable the JAR file to serve a variety of purposes.</p>
</blockquote>
<p>在可执行的JAR包中会指定<strong>MAIN-CLASS</strong>，作为JAR包启动的入口。</p>
<h3 id="FatJar"><a href="#FatJar" class="headerlink" title="FatJar"></a>FatJar</h3><p>普通的打包方式，会将所有类都掺杂在一起，而SpringBoot使用了FatJar将第三方的类放到lib目录下。项目所有的class都在BOOT-INF的classes目录下。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">├── BOOT-INF</span><br><span class="line">│   ├── classes</span><br><span class="line">│   │   ├── META-INF</span><br><span class="line">│   │   ├── application.properties</span><br><span class="line">│   │   └── com</span><br><span class="line">│   └── lib</span><br><span class="line">│       ├── classmate-1.5.1.jar</span><br><span class="line">│       ├── hibernate-validator-6.0.18.Final.jar</span><br><span class="line">│       ├── jackson-annotations-2.10.1.jar</span><br><span class="line">│       ├── jackson-core-2.10.1.jar</span><br><span class="line">│       ├── jackson-databind-2.10.1.jar</span><br><span class="line">│       ├── jackson-datatype-jdk8-2.10.1.jar</span><br><span class="line">│       ├── jackson-datatype-jsr310-2.10.1.jar</span><br><span class="line">│       ├── jackson-module-parameter-names-2.10.1.jar</span><br><span class="line">│       ├── jakarta.annotation-api-1.3.5.jar</span><br><span class="line">│       ├── jakarta.validation-api-2.0.1.jar</span><br><span class="line">│       ├── jboss-logging-3.4.1.Final.jar</span><br><span class="line">│       ├── jul-to-slf4j-1.7.29.jar</span><br><span class="line">│       ├── log4j-api-2.12.1.jar</span><br><span class="line">│       ├── log4j-to-slf4j-2.12.1.jar</span><br><span class="line">│       ├── logback-classic-1.2.3.jar</span><br><span class="line">│       ├── logback-core-1.2.3.jar</span><br><span class="line">│       ├── slf4j-api-1.7.29.jar</span><br><span class="line">│       ├── snakeyaml-1.25.jar</span><br><span class="line">│       ├── spring-aop-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-beans-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-autoconfigure-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-json-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-logging-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-tomcat-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-validation-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-web-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-context-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-core-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-expression-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-jcl-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-web-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-webmvc-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── tomcat-embed-core-9.0.29.jar</span><br><span class="line">│       ├── tomcat-embed-el-9.0.29.jar</span><br><span class="line">│       └── tomcat-embed-websocket-9.0.29.jar</span><br><span class="line">├── META-INF</span><br><span class="line">│   ├── MANIFEST.MF</span><br><span class="line">│   └── maven</span><br><span class="line">│       └── com.arry</span><br><span class="line">└── org</span><br><span class="line">    └── springframework</span><br><span class="line">        └── boot</span><br></pre></td></tr></table></figure>

<h3 id="自定义的ClassLoader"><a href="#自定义的ClassLoader" class="headerlink" title="自定义的ClassLoader"></a>自定义的ClassLoader</h3><p>因为改变了JAR包的结构，所以需要自定义ClassLoader来加载第三方包里的类。通过Manifest文件可以看出来，SpringBoot的jar包启动入口在JarLauncher。在launch方法里创建了<strong>LaunchedURLClassLoader</strong>。加载完类之后新建MethodRunner通过反射调用Start-Class的main方法。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Manifest-Version: 1.0</span><br><span class="line">Implementation-Title: demo</span><br><span class="line">Implementation-Version: 0.0.1-SNAPSHOT</span><br><span class="line">Start-Class: com.arry.demo.DemoApplication</span><br><span class="line">Spring-Boot-Classes: BOOT-INF/classes/</span><br><span class="line">Spring-Boot-Lib: BOOT-INF/lib/</span><br><span class="line">Build-Jdk-Spec: 1.8</span><br><span class="line">Spring-Boot-Version: 2.2.2.RELEASE</span><br><span class="line">Created-By: Maven Archiver 3.4.0</span><br><span class="line">Main-Class: org.springframework.boot.loader.JarLauncher</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">package</span> org.springframework.boot.loader;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.loader.archive.Archive;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.loader.archive.Archive.Entry;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JarLauncher</span> <span class="keyword">extends</span> <span class="title">ExecutableArchiveLauncher</span> </span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> String BOOT_INF_CLASSES = <span class="string">"BOOT-INF/classes/"</span>;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> String BOOT_INF_LIB = <span class="string">"BOOT-INF/lib/"</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">JarLauncher</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="title">JarLauncher</span><span class="params">(Archive archive)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(archive);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">isNestedArchive</span><span class="params">(Entry entry)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> entry.isDirectory() ? entry.getName().equals(<span class="string">"BOOT-INF/classes/"</span>) : entry.getName().startsWith(<span class="string">"BOOT-INF/lib/"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        (<span class="keyword">new</span> JarLauncher()).launch(args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">launch</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        JarFile.registerUrlProtocolHandler();</span><br><span class="line">        ClassLoader classLoader = <span class="keyword">this</span>.createClassLoader(<span class="keyword">this</span>.getClassPathArchives());</span><br><span class="line">        <span class="keyword">this</span>.launch(args, <span class="keyword">this</span>.getMainClass(), classLoader);</span><br><span class="line">&#125;</span><br><span class="line">---</span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">launch</span><span class="params">(String[] args, String mainClass, ClassLoader classLoader)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Thread.currentThread().setContextClassLoader(classLoader);</span><br><span class="line">        <span class="keyword">this</span>.createMainMethodRunner(mainClass, args, classLoader).run();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainMethodRunner</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> String mainClassName;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> String[] args;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MainMethodRunner</span><span class="params">(String mainClass, String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.mainClassName = mainClass;</span><br><span class="line">        <span class="keyword">this</span>.args = args != <span class="keyword">null</span> ? (String[])args.clone() : <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Class&lt;?&gt; mainClass = Thread.currentThread().getContextClassLoader().loadClass(<span class="keyword">this</span>.mainClassName);</span><br><span class="line">        Method mainMethod = mainClass.getDeclaredMethod(<span class="string">"main"</span>, String[].class);</span><br><span class="line">        mainMethod.invoke((Object)<span class="keyword">null</span>, <span class="keyword">this</span>.args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>自定义的LaunchedURLClassLoader会先在本地缓存中查询是否有类，如果没有的话，就需要遍历lib下的所有jar包，寻找要加载的Class。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">package</span> org.springframework.boot.loader;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LaunchedURLClassLoader</span> <span class="keyword">extends</span> <span class="title">URLClassLoader</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">LaunchedURLClassLoader</span><span class="params">(URL[] urls, ClassLoader parent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(urls, parent);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> URL <span class="title">findResource</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        URL var2;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            var2 = <span class="keyword">super</span>.findResource(name);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> var2;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Enumeration&lt;URL&gt; <span class="title">findResources</span><span class="params">(String name)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        LaunchedURLClassLoader.UseFastConnectionExceptionsEnumeration var2;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            var2 = <span class="keyword">new</span> LaunchedURLClassLoader.UseFastConnectionExceptionsEnumeration(<span class="keyword">super</span>.findResources(name));</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> var2;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> Class&lt;?&gt; loadClass(String name, <span class="keyword">boolean</span> resolve) <span class="keyword">throws</span> ClassNotFoundException &#123;</span><br><span class="line">        Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        Class var3;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">this</span>.definePackageIfNecessary(name);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (IllegalArgumentException var7) &#123;</span><br><span class="line">                <span class="keyword">if</span> (<span class="keyword">this</span>.getPackage(name) == <span class="keyword">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> AssertionError(<span class="string">"Package "</span> + name + <span class="string">" has already been defined but it could not be found"</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            var3 = <span class="keyword">super</span>.loadClass(name, resolve);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> var3;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">definePackageIfNecessary</span><span class="params">(String className)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> lastDot = className.lastIndexOf(<span class="number">46</span>);</span><br><span class="line">        <span class="keyword">if</span> (lastDot &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">            String packageName = className.substring(<span class="number">0</span>, lastDot);</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">this</span>.getPackage(packageName) == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="keyword">this</span>.definePackage(className, packageName);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (IllegalArgumentException var5) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (<span class="keyword">this</span>.getPackage(packageName) == <span class="keyword">null</span>) &#123;</span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> AssertionError(<span class="string">"Package "</span> + packageName + <span class="string">" has already been defined but it could not be found"</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">definePackage</span><span class="params">(String className, String packageName)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            AccessController.doPrivileged(() -&gt; &#123;</span><br><span class="line">                String packageEntryName = packageName.replace(<span class="string">'.'</span>, <span class="string">'/'</span>) + <span class="string">"/"</span>;</span><br><span class="line">                String classEntryName = className.replace(<span class="string">'.'</span>, <span class="string">'/'</span>) + <span class="string">".class"</span>;</span><br><span class="line">                URL[] var5 = <span class="keyword">this</span>.getURLs();</span><br><span class="line">                <span class="keyword">int</span> var6 = var5.length;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">for</span>(<span class="keyword">int</span> var7 = <span class="number">0</span>; var7 &lt; var6; ++var7) &#123;</span><br><span class="line">                    URL url = var5[var7];</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        URLConnection connection = url.openConnection();</span><br><span class="line">                        <span class="keyword">if</span> (connection <span class="keyword">instanceof</span> JarURLConnection) &#123;</span><br><span class="line">                            JarFile jarFile = ((JarURLConnection)connection).getJarFile();</span><br><span class="line">                            <span class="keyword">if</span> (jarFile.getEntry(classEntryName) != <span class="keyword">null</span> &amp;&amp; jarFile.getEntry(packageEntryName) != <span class="keyword">null</span> &amp;&amp; jarFile.getManifest() != <span class="keyword">null</span>) &#123;</span><br><span class="line">                                <span class="keyword">this</span>.definePackage(packageName, jarFile.getManifest(), url);</span><br><span class="line">                                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (IOException var11) &#123;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;, AccessController.getContext());</span><br><span class="line">        &#125; <span class="keyword">catch</span> (PrivilegedActionException var4) &#123;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">clearCache</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        URL[] var1 = <span class="keyword">this</span>.getURLs();</span><br><span class="line">        <span class="keyword">int</span> var2 = var1.length;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> var3 = <span class="number">0</span>; var3 &lt; var2; ++var3) &#123;</span><br><span class="line">            URL url = var1[var3];</span><br><span class="line"></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                URLConnection connection = url.openConnection();</span><br><span class="line">                <span class="keyword">if</span> (connection <span class="keyword">instanceof</span> JarURLConnection) &#123;</span><br><span class="line">                    <span class="keyword">this</span>.clearCache(connection);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (IOException var6) &#123;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">clearCache</span><span class="params">(URLConnection connection)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Object jarFile = ((JarURLConnection)connection).getJarFile();</span><br><span class="line">        <span class="keyword">if</span> (jarFile <span class="keyword">instanceof</span> org.springframework.boot.loader.jar.JarFile) &#123;</span><br><span class="line">            ((org.springframework.boot.loader.jar.JarFile)jarFile).clearCache();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        ClassLoader.registerAsParallelCapable();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">UseFastConnectionExceptionsEnumeration</span> <span class="keyword">implements</span> <span class="title">Enumeration</span>&lt;<span class="title">URL</span>&gt; </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">final</span> Enumeration&lt;URL&gt; delegate;</span><br><span class="line"></span><br><span class="line">        UseFastConnectionExceptionsEnumeration(Enumeration&lt;URL&gt; delegate) &#123;</span><br><span class="line">            <span class="keyword">this</span>.delegate = delegate;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasMoreElements</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">boolean</span> var1;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                var1 = <span class="keyword">this</span>.delegate.hasMoreElements();</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> var1;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> URL <span class="title">nextElement</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">            URL var1;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                var1 = (URL)<span class="keyword">this</span>.delegate.nextElement();</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> var1;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Manifest-Version: <span class="number">1.0</span></span><br><span class="line">Main-Class: Hello</span><br></pre></td></tr></table></figure>


          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/dubbo/import/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/dubbo/import/" itemprop="url">dubbo导入</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-12-02T10:14:03+08:00">
                2019-12-02
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/dubbo/" itemprop="url" rel="index">
                    <span itemprop="name">dubbo</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/dubbo/directory/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/dubbo/directory/" itemprop="url">服务目录</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-12T11:17:33+08:00">
                2019-11-12
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/dubbo/" itemprop="url" rel="index">
                    <span itemprop="name">dubbo</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="RegistryDirectory"><a href="#RegistryDirectory" class="headerlink" title="RegistryDirectory"></a>RegistryDirectory</h3><p>RegistryDirectory实现了NotifyListener接口，会在注册中心变更时刷新Invoker列表。</p>
<h4 id="doList"><a href="#doList" class="headerlink" title="doList"></a>doList</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> List&lt;Invoker&lt;T&gt;&gt; doList(Invocation invocation) &#123;</span><br><span class="line">    <span class="keyword">if</span> (forbidden) &#123;</span><br><span class="line">        <span class="comment">// 1. No service provider 2. Service providers are disabled</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> RpcException(RpcException.FORBIDDEN_EXCEPTION,</span><br><span class="line">            <span class="string">"No provider available from registry "</span> + getUrl().getAddress() + <span class="string">" for service "</span> + getConsumerUrl().getServiceKey() + <span class="string">" on consumer "</span> +  NetUtils.getLocalHost()</span><br><span class="line">                    + <span class="string">" use dubbo version "</span> + Version.getVersion() + <span class="string">", please check status of providers(disabled, not registered or in blacklist)."</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    List&lt;Invoker&lt;T&gt;&gt; invokers = <span class="keyword">null</span>;</span><br><span class="line">  <span class="comment">// 加载本地方法列表</span></span><br><span class="line">    Map&lt;String, List&lt;Invoker&lt;T&gt;&gt;&gt; localMethodInvokerMap = <span class="keyword">this</span>.methodInvokerMap; <span class="comment">// local reference</span></span><br><span class="line">    <span class="keyword">if</span> (localMethodInvokerMap != <span class="keyword">null</span> &amp;&amp; localMethodInvokerMap.size() &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        String methodName = RpcUtils.getMethodName(invocation);</span><br><span class="line">        Object[] args = RpcUtils.getArguments(invocation);</span><br><span class="line">      <span class="comment">// 通过方法名+参数获取invoker列表</span></span><br><span class="line">        <span class="keyword">if</span> (args != <span class="keyword">null</span> &amp;&amp; args.length &gt; <span class="number">0</span> &amp;&amp; args[<span class="number">0</span>] != <span class="keyword">null</span></span><br><span class="line">                &amp;&amp; (args[<span class="number">0</span>] <span class="keyword">instanceof</span> String || args[<span class="number">0</span>].getClass().isEnum())) &#123;</span><br><span class="line">            invokers = localMethodInvokerMap.get(methodName + <span class="string">"."</span> + args[<span class="number">0</span>]); <span class="comment">// The routing can be enumerated according to the first parameter</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (invokers == <span class="keyword">null</span>) &#123;</span><br><span class="line">            invokers = localMethodInvokerMap.get(methodName);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (invokers == <span class="keyword">null</span>) &#123;</span><br><span class="line">            invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (invokers == <span class="keyword">null</span>) &#123;</span><br><span class="line">            Iterator&lt;List&lt;Invoker&lt;T&gt;&gt;&gt; iterator = localMethodInvokerMap.values().iterator();</span><br><span class="line">            <span class="keyword">if</span> (iterator.hasNext()) &#123;</span><br><span class="line">                invokers = iterator.next();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> invokers == <span class="keyword">null</span> ? <span class="keyword">new</span> ArrayList&lt;Invoker&lt;T&gt;&gt;(<span class="number">0</span>) : invokers;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>####服务接受通知</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">notify</span><span class="params">(List&lt;URL&gt; urls)</span> </span>&#123;</span><br><span class="line">    List&lt;URL&gt; invokerUrls = <span class="keyword">new</span> ArrayList&lt;URL&gt;();</span><br><span class="line">    List&lt;URL&gt; routerUrls = <span class="keyword">new</span> ArrayList&lt;URL&gt;();</span><br><span class="line">    List&lt;URL&gt; configuratorUrls = <span class="keyword">new</span> ArrayList&lt;URL&gt;();</span><br><span class="line">    <span class="keyword">for</span> (URL url : urls) &#123;</span><br><span class="line">        String protocol = url.getProtocol();</span><br><span class="line">        String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);</span><br><span class="line">        <span class="keyword">if</span> (Constants.ROUTERS_CATEGORY.equals(category)</span><br><span class="line">                || Constants.ROUTE_PROTOCOL.equals(protocol)) &#123;</span><br><span class="line">            routerUrls.add(url);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (Constants.CONFIGURATORS_CATEGORY.equals(category)</span><br><span class="line">                || Constants.OVERRIDE_PROTOCOL.equals(protocol)) &#123;</span><br><span class="line">            configuratorUrls.add(url);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (Constants.PROVIDERS_CATEGORY.equals(category)) &#123;</span><br><span class="line">            invokerUrls.add(url);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            logger.warn(<span class="string">"Unsupported category "</span> + category + <span class="string">" in notified url: "</span> + url + <span class="string">" from registry "</span> + getUrl().getAddress() + <span class="string">" to consumer "</span> + NetUtils.getLocalHost());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// configurators</span></span><br><span class="line">    <span class="keyword">if</span> (configuratorUrls != <span class="keyword">null</span> &amp;&amp; !configuratorUrls.isEmpty()) &#123;</span><br><span class="line">        <span class="keyword">this</span>.configurators = toConfigurators(configuratorUrls);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// routers</span></span><br><span class="line">    <span class="keyword">if</span> (routerUrls != <span class="keyword">null</span> &amp;&amp; !routerUrls.isEmpty()) &#123;</span><br><span class="line">        List&lt;Router&gt; routers = toRouters(routerUrls);</span><br><span class="line">        <span class="keyword">if</span> (routers != <span class="keyword">null</span>) &#123; <span class="comment">// null - do nothing</span></span><br><span class="line">            setRouters(routers);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    List&lt;Configurator&gt; localConfigurators = <span class="keyword">this</span>.configurators; <span class="comment">// local reference</span></span><br><span class="line">    <span class="comment">// merge override parameters</span></span><br><span class="line">    <span class="keyword">this</span>.overrideDirectoryUrl = directoryUrl;</span><br><span class="line">    <span class="keyword">if</span> (localConfigurators != <span class="keyword">null</span> &amp;&amp; !localConfigurators.isEmpty()) &#123;</span><br><span class="line">        <span class="keyword">for</span> (Configurator configurator : localConfigurators) &#123;</span><br><span class="line">            <span class="keyword">this</span>.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// providers</span></span><br><span class="line">    refreshInvoker(invokerUrls);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/mysql/锁/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/mysql/锁/" itemprop="url">锁</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-05T09:54:08+08:00">
                2019-11-05
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/mysql/" itemprop="url" rel="index">
                    <span itemprop="name">mysql</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="锁结构"><a href="#锁结构" class="headerlink" title="锁结构"></a>锁结构</h2><ul>
<li>trxid：事务ID</li>
<li>is_waiting：获取锁成功就是false，失败就是true，阻塞等待</li>
</ul>
<h2 id="表锁"><a href="#表锁" class="headerlink" title="表锁"></a>表锁</h2><p>MySQL仅在DDL语句执行的时候会加上表锁X、S锁，或者手动Lock table。当对表的纪录加锁的时候，会加上意向锁。</p>
<ul>
<li>共享锁</li>
<li>独占锁</li>
<li>意向共享锁</li>
<li>意向独占锁</li>
</ul>
<h3 id="一致性读（快照读）"><a href="#一致性读（快照读）" class="headerlink" title="一致性读（快照读）"></a>一致性读（快照读）</h3><p>通过MVCC，不加锁读取记录</p>
<h3 id="锁定读"><a href="#锁定读" class="headerlink" title="锁定读"></a>锁定读</h3><p>除了手动加锁，在进行修改删除的操作时也会先锁记录，再进行其他操作。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1. <span class="keyword">select</span> * <span class="keyword">from</span> …… <span class="keyword">in</span> <span class="keyword">share</span> <span class="keyword">mode</span></span><br><span class="line"><span class="number">2.</span> <span class="keyword">Select</span> * <span class="keyword">from</span> …… <span class="keyword">for</span> <span class="keyword">update</span>;</span><br><span class="line">3. <span class="keyword">delete</span> ……</span><br><span class="line"><span class="number">4.</span> <span class="keyword">update</span> ……</span><br></pre></td></tr></table></figure>

<h3 id="写操作"><a href="#写操作" class="headerlink" title="写操作"></a>写操作</h3><ul>
<li><p>delete</p>
<p>相当于获取X锁的读，然后再做delete mark</p>
</li>
<li><p>update</p>
<ul>
<li>不更新主键，就地更新，相当于获取原纪录的X锁</li>
<li>更新列值要先获取原纪录的x锁，然后insert是隐式锁</li>
</ul>
</li>
<li><p>insert</p>
<p>隐式锁</p>
</li>
</ul>
<h2 id="行锁"><a href="#行锁" class="headerlink" title="行锁"></a>行锁</h2><h3 id="Record-Lock"><a href="#Record-Lock" class="headerlink" title="Record Lock"></a>Record Lock</h3><p>锁纪录</p>
<h3 id="Gap-Lock"><a href="#Gap-Lock" class="headerlink" title="Gap Lock"></a>Gap Lock</h3><p>锁间隙</p>
<h4 id="READ-UNCOMMITTED-READ-COMMITTED隔离级别下"><a href="#READ-UNCOMMITTED-READ-COMMITTED隔离级别下" class="headerlink" title="READ UNCOMMITTED/READ COMMITTED隔离级别下"></a>READ UNCOMMITTED/READ COMMITTED隔离级别下</h4><h5 id="主键等值查询"><a href="#主键等值查询" class="headerlink" title="主键等值查询"></a>主键等值查询</h5><p>1/2直接对记录加锁，share mode加共享锁，for update 加排他锁</p>
<p>在删除和更新记录的时候，除了要对聚簇索引的数据进行操作，还需要更新二级索引的数据，所以会</p>
<ol>
<li>先给聚簇索引的数据加锁</li>
<li>给二级索引加锁。</li>
</ol>
<h5 id="主键范围查询"><a href="#主键范围查询" class="headerlink" title="主键范围查询"></a>主键范围查询</h5><p>在<strong>select …… in share mode / for update</strong>下查询数据的步骤是类似的，不过加的锁不一样</p>
<p>比如</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> t1 <span class="keyword">where</span> t1.id &lt; <span class="number">10</span> <span class="keyword">in</span> <span class="keyword">share</span> <span class="keyword">mode</span>;</span><br></pre></td></tr></table></figure>

<ol>
<li>从聚簇索引中定位到满足条件的第一条数据</li>
<li>判断是否满足索引下移</li>
<li>是否满足<strong>范围查询</strong>条件，如果满足<strong>范围条件</strong>就返回给server层（t1.id&lt;10），不满足直接结束查询。</li>
<li>server层再进行其他条件的判断，如果满足就返回客户端，不满足就释放该条记录的锁。</li>
<li>重复234遍历链表，直到不满足条件为止</li>
</ol>
<p>在<strong>update/delete</strong>的情况下</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">delete</span> * <span class="keyword">from</span> t1 <span class="keyword">where</span> t1.id &gt; <span class="number">8</span>;</span><br></pre></td></tr></table></figure>

<p>和select的模式是一样的，区别除了先对聚簇索引加锁，还需要对更新了的二级索引进行加锁。这里的锁都是排他锁。</p>
<h5 id="二级索引等值查询"><a href="#二级索引等值查询" class="headerlink" title="二级索引等值查询"></a>二级索引等值查询</h5>
          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/mysql/undo/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/blog/mysql/undo/" itemprop="url">undoLog</a></h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-11-04T09:45:34+08:00">
                2019-11-04
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/mysql/" itemprop="url" rel="index">
                    <span itemprop="name">mysql</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>MySQL的事务需要保证原子性，所以在事务中的操作要不全部完成，要不就全部不执行，如果执行到一半的时候要回滚，那innoDB该怎么处理。这里就需要undolog来记录回滚所需要的操作。</p>
<ul>
<li>事务ID<ul>
<li>分配时机：在某个事务中对一个表执行了update、insert、delete操作，那么就会分配一个事务ID。</li>
<li>生成规则：服务器在内存中维护一个最大事务ID，这个事务ID是递增的。</li>
<li>行记录会保存一个事务ID</li>
</ul>
</li>
<li>Undo log<ul>
<li>在实际进行增、删、改一条记录时，都需要先把undo log记录下来。</li>
<li>每次改动都会产生一个undo log，某些更新会产生两条undo log</li>
<li>insert格式<ul>
<li>主键列信息</li>
<li>表id</li>
<li>日志编号</li>
</ul>
</li>
<li>delete<ul>
<li>删除过程<ul>
<li>阶段一：delete mark，修改删除标志位，但其实还未实际删除</li>
<li>阶段二：purge，将删除记录加入到free链表中</li>
</ul>
</li>
<li>格式<ul>
<li>旧的trxid</li>
<li>旧的roll_pointer值（指向之前一条undo log）</li>
<li>主键列</li>
<li>表id</li>
<li>日志编号</li>
<li>被索引的各列信息</li>
</ul>
</li>
</ul>
</li>
<li>update<ul>
<li>不更新主键<ul>
<li>就地更新：修改前后的每一列占用大小不变，则直接在原纪录上更新。</li>
<li>先删除后更新 ：修改前后有列的占用大小变了，那么就直接<strong>删除（非delete mark）</strong>原记录，并新增一条记录</li>
<li>格式<ul>
<li>旧的trxid</li>
<li>旧的roll_pointer值（指向之前一条undo log）</li>
<li>主键列</li>
<li>表id</li>
<li>日志编号</li>
<li>被索引的各列信息</li>
<li>修改的列信息</li>
</ul>
</li>
</ul>
</li>
<li>更新主键<ul>
<li>delete mark</li>
<li>新增一条新记录</li>
<li>事务提交后purge删除原记录</li>
<li>格式<ul>
<li>记录一条删除的undo log</li>
<li>记录一条insert的undo log</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

          
        
      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/blog/page/2/"><i class="fa fa-angle-left"></i></a><a class="page-number" href="/blog/">1</a><a class="page-number" href="/blog/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/blog/page/4/">4</a><a class="page-number" href="/blog/page/5/">5</a><a class="extend next" rel="next" href="/blog/page/4/"><i class="fa fa-angle-right"></i></a>
  </nav>



          </div>
          


          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/blog/uploads/avatar.jpg" alt="arry">
            
              <p class="site-author-name" itemprop="name">arry</p>
              <p class="site-description motion-element" itemprop="description">Java源码/设计模式/个人记录</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blog/archives/">
              
                  <span class="site-state-item-count">42</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/blog/categories/index.html">
                  <span class="site-state-item-count">11</span>
                  <span class="site-state-item-name">categories</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/blog/tags/index.html">
                  <span class="site-state-item-count">18</span>
                  <span class="site-state-item-name">tags</span>
                </a>
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">arry</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.4"></script>



  
  

  

  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
